package org.gruposp2p.proyectokarma.gwt.client.cometd;

import java.util.HashMap;
import java.util.Map;
import org.cometd4gwt.client.CometConnectionListener;
import org.cometd4gwt.client.CometMessageConsumer;
import org.cometd4gwt.client.CometdClient;
import org.cometd4gwt.client.CometdClientImpl;
import org.cometd4gwt.client.CometdJso;
import org.cometd4gwt.client.ConnectionConfig;
import org.cometd4gwt.client.JsoListener;
import org.cometd4gwt.client.PersistentSubscribersCometdClient;
import org.cometd4gwt.client.ScriptLoadListener;
import org.gruposp2p.proyectokarma.gwt.client.domain.CometdMetaMessage;
import org.gruposp2p.proyectokarma.gwt.client.domain.CometdMessage;
import org.gruposp2p.proyectokarma.gwt.client.json.DomainToJSON;
import org.gruposp2p.proyectokarma.gwt.client.json.JSONToDomain;
import org.gruposp2p.proyectokarma.gwt.client.util.ServerPaths;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.allen_sauer.gwt.log.client.Log;

public class GroupManagerPanel extends Composite {
	
    private static GroupManagerPanelUiBinder uiBinder = 
    	GWT.create(GroupManagerPanelUiBinder.class);

    interface GroupManagerPanelUiBinder extends UiBinder<Widget, GroupManagerPanel> { }

    @UiField Button joinToGroup;
    @UiField Button leaveGroup;
    @UiField Button sendMessageToGroup;  
    @UiField TextBox messageToSend;
    @UiField TextBox messageToSendSubject;
    @UiField HTML status;
    @UiField TextBox groupToJoin;
    @UiField TextBox groupToLeave;
    @UiField TextBox peerFrom;
    @UiField TextBox peerTo;
    boolean connected;
    private ConnectionConfig connectionConfig;
     
	final CometdClient cometdClient = 
		new PersistentSubscribersCometdClient(new CometdClientImpl());
	
	private Map<String, JavaScriptObject> subscriptions = new HashMap<String, JavaScriptObject> ();
	
    public GroupManagerPanel() {
    	initWidget(uiBinder.createAndBindUi(this));
    	connected = false;
    	cometdClient.addConnectionListener(new CometConnectionListener() {
			@Override
			public void onConnected() {
				Log.debug("#### Connected ####");
				connected = true;
			}

			@Override
			public void onDisconnected() {
				Log.debug("#### Disconnected ####");
				connected = false;
			}
		});
		cometdClient.addScriptLoadListener(new ScriptLoadListener() {
			@Override
			public void onLoad() {
				cometdClient.addListener("/meta/*", new JsoListener<CometdJso>() {
					@Override
					public void onMessageReceived(CometdJso metaMessage) {
						CometdMetaMessage message = 
							JSONToDomain.getCometdMetaMessage(new JSONObject(metaMessage)); 
						logCometdActivity (message, metaMessage);
					}
				});
			}
		});
		connectionConfig = new ConnectionConfig(ServerPaths.COMETD_SERVICE);
		connectionConfig.requestHeaderName = "userId";
		connectionConfig.requestHeaderValue = "" + ((int) (Math.random() * 1000));
		//connectionConfig.requestHeaderValue = " - cabezorrin de los bosques - ";
		cometdClient.connect(connectionConfig);
    }
    
    public void setStatusMessage (String message) {
    	status.setHTML(message);
    }
    
    @UiHandler("sendMessageToGroup")
    void handleSendMessageToGroup(ClickEvent e) {
    	String selectedChannel;
    	String to = peerTo.getSelectedText();
    	if ("".equals(to) || to == null) {
    		//message to group
    		selectedChannel = ChannelOf.getAreaChanel(groupToJoin.getSelectedText());
    	} else {
    		//selectedChannel = ChannelOf.PRIVATE_CHANNEL;
    	}
    	/*CometdMessage groupMessage = new CometdMessage (groupToJoin.getSelectedText(),
    			peerFrom.getSelectedText(), peerTo.getSelectedText(), "TopSecret", 
    			"testAction", messageToSend.getSelectedText(), messageToSendSubject.getSelectedText(), 
    			selectedChannel);
    	sendMessage(groupMessage);*/
    }
    
    @UiHandler("joinToGroup")
    void handleJoinToGroup(ClickEvent e) {
    	String selectedGroup = groupToJoin.getValue();
    	Log.debug("selectedGroup: " + selectedGroup);
    	String selectedChannel;
    	if ("".equals(selectedGroup) || selectedGroup == null) {
    		//message to group
    		//selectedChannel = ChannelOf.PRIVATE_CHANNEL;
    	} else {
    		selectedChannel = ChannelOf.getAreaChanel(selectedGroup);
    	}
    	//join(selectedChannel);
    }
	
	private void leave (String channel) {
		JavaScriptObject subscription = subscriptions.get(channel);
		if (subscription != null) {
			CometdBatchHelper.beginBatch();
			CometdMessage message = new CometdMessage(null,
					peerFrom.getSelectedText(), null, null, 
					"leave", null, null, channel);
			sendMessage(message);
			cometdClient.unsubscribe(subscription);
			CometdBatchHelper.endBatch();
			subscriptions.remove(channel);
			Log.debug(" Unsubscribed from channel: " + channel);
		} else { 
			Log.debug(" NULL SUBSCRIP: " + channel);
		}
	}
	
	private void join (final String channel) {
		/*final JavaScriptObject subscription = cometdClient.addSubscriber(channel,
				new CometMessageConsumer() {
					@Override
					public void onMessageReceived(IsSerializable message) {
						Log.debug("MENSAJE RECIBIDO!!! - Canal: " + channel + "-- message: " + message);
					}
				}, new JsoListener<Subscription>() {
					@Override
					public void onMessageReceived(Subscription subscription) {
						Log.debug("@@ Subscription: " + subscription._toString());
					}
				});*/
		//subscriptions.put(channel, subscription);
	}
	
	private void sendMessage (CometdMessage groupMessage) {
		JavaScriptObject subscription = subscriptions.get(groupMessage.channel);
		if (subscription == null) {
			join(groupMessage.channel);
		}
		cometdClient.publish(groupMessage.channel, 
				DomainToJSON.getCometdMessage(groupMessage).toString());
	}
	
	private String channel;
	private void logCometdActivity (CometdMetaMessage message, CometdJso metaMessage) {
		if (channel != null && channel.equals(message.channel)) return;
		channel = message.channel;
		//Log.debug(" CometdMetaMessage: " + message._toString());
		Log.debug(" metaMessage: " + new JSONObject(metaMessage));
	}

	
}